package ca.ubc.cs304.library.sql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

public class OracleDatabaseWrapper {
	
	
	/**
	 * The singleton instance
	 */
	private static OracleDatabaseWrapper fInstance = null;
	
	
	/**
	 * The connection
	 */
	private Connection fConnection;	
	
	
	/**
	 * Make the constructor private - this is a singleton
	 */
	private OracleDatabaseWrapper() {
		// :-p singleton. We keep our constructors private!
	}

	/**
	 * Get an instance of the present wrapper, or creates if it doesn't exist
	 * @return
	 */
	synchronized public static OracleDatabaseWrapper getInstance() {
		if (fInstance == null) 
			fInstance = new OracleDatabaseWrapper();
		return fInstance;
	}
	
	/**
	 * Connects to a database
	 * @param username - the username to use
	 * @param password - your password
	 * @param location - the connection string
	 * @return true on success, false on failure
	 * @throws SQLException - if any problems arise.
	 */
	public boolean connect(String username, String password, String location) throws SQLException {
		
		// limits number of connections to 1 so we don't overwrite connections while we use our program
		
		// Deprecated branch: The gui handles this event
		//if (isConnected()) {
		//	System.err.println("Warning! Already connected to a database! Disconnect first!");
		//	return true;
		//}

		fInstance =  this;
		
		DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());

		fConnection = DriverManager.getConnection(location, username, password);
		
		return !fConnection.isClosed();
	}

	/**
	 * Closes an open connection
	 * @return
	 * @throws SQLException
	 */
	public boolean closeConnect() throws SQLException {
		fConnection.close();
		return fConnection.isClosed();
	}
	
	/**
	 * Checks if the connection is open
	 * @return true if it is, and false if it's not
	 */
	public boolean isConnected() {
		try {
			return !fConnection.isClosed();
		} catch (SQLException e) {
			e.printStackTrace();
			return false; // Some error occurred
		} catch (NullPointerException e) {
			return false; // fConnection was null
		}
	}
	
	/**
	 * Prepares an SQL prepared statement
	 * @param sqlQuery - the query to prep, as a string
	 * @return - a prepared statement
	 * @throws SQLException on any SQL errors
	 */
	public PreparedStatement createPreparedStatement(String sqlQuery) throws SQLException {
		if (fConnection == null) {
			throw new SQLException("You might want to call OracleDatabaseWrapper.connect() first :-)");
		}
		return fConnection.prepareStatement(sqlQuery);
	}

	/**
	 * Creates an sql statement
	 * @return the statement
	 * @throws SQLException on any SQL errors
	 */
	public Statement createStatement() throws SQLException {
		if (fConnection == null) {
			throw new SQLException("You might want to call OracleDatabaseWrapper.connect() first :-)");
		}
		return fConnection.createStatement();
	}
	
	/**
	 * Commits changes if SQL auto-commit has been disabled
	 * @throws SQLException
	 */
	public void commit() throws SQLException {
		if (fConnection == null) {
			throw new SQLException("You might want to call OracleDatabaseWrapper.connect() first :-)");
		}
		fConnection.commit();
	}
}
